home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / pascal / paswiz15.zip / PASWIZ.DOC < prev    next >
Text File  |  1993-08-04  |  50KB  |  1,404 lines

  1.                   The Pascal Wizard's Library
  2.                   =-------------------------=
  3.                           Version 1.5
  4.  
  5.     PasWiz  Copyright (c) 1990-1993  Thomas G. Hanlin III
  6.  
  7.  
  8.  
  9. This is PasWiz, a library of assorted routines for use with
  10. Turbo Pascal, Quick Pascal, and compatible compilers. Full
  11. Pascal source code is now included with the shareware version.
  12. Assembly language sources are provided to registered owners. The
  13. PasWiz collection is copyrighted, but may be distributed as long
  14. as the following conditions are met:
  15.  
  16.    All PasWiz files must be distributed together as a unit in
  17.    unmodified form. No files may be left out or added.
  18.  
  19. YOU USE THIS LIBRARY AT YOUR OWN RISK. It has been tested by me
  20. on my own computer, but I will not assume any responsibility for
  21. any problems which PasWiz may cause you. If you run into a
  22. problem, please let me know about it, and I will do my best to
  23. verify and repair the error.
  24.  
  25. Shareware operates on a "try before you buy" basis. It is
  26. expected that if you find PasWiz useful, you will register your
  27. copy. You may not use PasWiz routines in programs intended for
  28. distribution unless you have registered. Registration entitles
  29. you to receive the latest version of PasWiz, complete with full
  30. source code. See the ORDER.FRM file for details.
  31.  
  32. So who's the Pascal Wizard? With PasWiz, you are! Read this tome
  33. well, for invoking these routines without proper preparation may
  34. bring unexpected results. Cape and hat (optional) not included.
  35.  
  36.                       Table of Contents                  page 2
  37.  
  38.  
  39.  
  40.  Overview and Legal Info .................................... 1
  41.  
  42.  Archive Directories ........................................ 3
  43.  
  44.  BCD Math ................................................... 5
  45.  
  46.  Equipment Info ............................................. 9
  47.  
  48.  Expression Evaluator ...................................... 12
  49.  
  50.  Extensions to Pascal's Math ............................... 13
  51.  
  52.  Joystick Support .......................................... 15
  53.  
  54.  Keyboard Control .......................................... 16
  55.  
  56.  String Stuff .............................................. 20
  57.  
  58.  Music ..................................................... 24
  59.  
  60.  Mouse ..................................................... 25
  61.  
  62.                       Archive Directories                 page 3
  63.  
  64.                         Unit: Archives
  65.  
  66.  
  67.  
  68. When I started in the microcomputer industry, there was a small
  69. variety of file archivers, all (more or less) compatible. They
  70. did not provide compression, which was relegated to another
  71. large selection of more-or-less compatible utilities. Then came
  72. SEA's ARC. It was very slow, but it did compression as well as
  73. archiving, and included CRC checks so you could know whether the
  74. files were intact. It swept the BBS scene in short order,
  75. becoming the new standard. A few other archivers competed on
  76. about a level footing, providing only minor variances on the ARC
  77. theme. Then SEA decided to sue one of their more successful
  78. competitors, Phil Katz (PKARC). The end result was PKZIP, which
  79. totally blew ARC away-- a useful hint to companies that choose
  80. to litigate instead of innovate. In the chaos resulting from the
  81. breaking of the former ARC standard, many other archivers came
  82. into being: ARJ, LZH, PAK, ZOO, et al.
  83.  
  84. PBWiz helps resolve the confusion by providing a single set of
  85. routines which allow you to view the contents of archives in any
  86. of the above-mentioned formats: ARJ, LZH, PAK, ZIP, ZOO, and
  87. even the antique ARC protocol. It also handles self-extracting
  88. EXE files of the forms produced by ARJ, LHARC and ZIP2EXE. Only
  89. archive directories are provided at this time. Other formats
  90. will also be added as they arise. If you have details on the
  91. format of an archive that you'd like me to add to PBWiz, please
  92. send them my way.
  93.  
  94. Viewing archive directories is handled in roughly the same
  95. fashion as you might view a DOS file directory. This makes it
  96. possible to treat an archive and a subdirectory in a similar
  97. manner, as long as the archive doesn't contain archives itself.
  98.  
  99. When you're looking for the first file in an archive, use the
  100. FindFirstA function. You must specify the archive name and a
  101. file name. The archive name may include a drive and path
  102. specification, and does not need to have the archive extension.
  103. If you leave off the extension, FindFirstA will use the first
  104. archive it comes across that matches the rest of the
  105. specification. Note that the archive specification may not
  106. contain wildcards. In contrast, the search file name may not
  107. contain drive or path specs, but may contain wildcards.
  108.  
  109. PROCEDURE FindFirstA (ArchiveName, FileName: String;
  110.                       VAR ErrCode: Integer);
  111.  
  112.  
  113.                       Archive Directories                 page 4
  114.  
  115.                         Unit: Archives
  116.  
  117.  
  118.  
  119. If there are no files to be found, or if the archive
  120. specification was bad, an error code will be returned. If there
  121. was no error, there may well be more files to be found. You can
  122. find each of them with FindNextA:
  123.  
  124. FindNextA (VAR ErrCode: Integer);
  125.  
  126. Of course, just finding a matching file doesn't do you much good
  127. unless you can retrieve information about it. You can use any of
  128. the following routines to provide information about a matched
  129. file:
  130.  
  131. FUNCTION GetNameA: String;    { file name }
  132. FUNCTION GetDateA: String;    { file date }
  133. FUNCTION GetTimeA: String;    { file time (24-hour) }
  134. FUNCTION GetCRCA: String;     { file CRC (8-char hexadecimal) }
  135. FUNCTION GetStoreA: String;   { file storage method }
  136.  
  137. PROCEDURE GetSizeA (VAR OriginalSize: LongInt;
  138.                     VAR CurrentSize: LongInt);
  139.  
  140. When you're done viewing an archive, be sure to close it:
  141.  
  142. PROCEDURE CloseA;
  143.  
  144. Let's try an example, to view all files in an archive:
  145.  
  146.    USES
  147.       Archives;
  148.    VAR
  149.       ErrCode: Integer;
  150.    BEGIN
  151.       IF ParamCount = 1 THEN BEGIN
  152.          FindFirstA(ParamStr(1), '*.*', ErrCode)
  153.          WHILE ErrCode = 0 DO BEGIN
  154.             WriteLn(GetNameA);
  155.             FindNextA(ErrCode);
  156.          END;
  157.          CloseA;
  158.       END
  159.       ELSE
  160.          WriteLn('Archive name expected');
  161.    END.
  162.  
  163.                            BCD Math                      page 5
  164.  
  165.                            Unit: BCD
  166.  
  167.  
  168.  
  169. Some of you may not have heard of BCD math, or at least not have
  170. more than a passing acquaintance with the subject. BCD (short
  171. for Binary-Coded Decimal) is a way of encoding numbers. It
  172. differs from the normal method of handling numbers in several
  173. respects. On the down side, BCD math is much slower than normal
  174. math and the numbers take up more memory. However, the benefits
  175. may far outweigh these disadvantages, depending on your
  176. application: BCD math is absolutely precise within your desired
  177. specifications, and you can make a BCD number as large as you
  178. need. If your applications don't require great range or
  179. precision out of numbers, normal Pascal math is probably the
  180. best choice. For scientific applications, accounting,
  181. engineering and other demanding tasks, though, BCD may be just
  182. the thing you need.
  183.  
  184. The BCD math routines provided by PasWiz allow numbers of up to
  185. 255 digits long (the sign counts as a digit, but the decimal
  186. point doesn't). You may set the decimal point to any position
  187. you like, as long as there is at least one digit position to the
  188. left of the decimal.
  189.  
  190. Since Pascal doesn't support BCD numbers directly, we store the
  191. BCD numbers in strings. The results are not in text format and
  192. won't mean much if displayed. A conversion routine allows you to
  193. change a BCD number to a text string in any of a variety of
  194. formats.
  195.  
  196. Note that the BCD math handler doesn't yet track
  197. overflow/underflow error conditions. If you anticipate that this
  198. may be a problem, it would be a good idea to screen your input
  199. or to make the BCD range large enough to avoid these errors.
  200.  
  201. Let's start off by considering the BCD range. This is kept in
  202. two integer variables, LDigits and RDigits, which can be
  203. accessed by your program. These variables specify the maximum
  204. number of digits to the left and to the right of the decimal
  205. point. There must be at least one digit on the left, and the
  206. total number of digits must be less than 255. The BCD strings
  207. will have a length that's one larger than the total number of
  208. digits, to account for the sign of the number. The decimal point
  209. is implicit and doesn't take up any extra space.
  210.  
  211. It is assumed that you will only use one size of BCD number in
  212. your program-- there are no provisions for handling mixed-length
  213. BCD numbers. Of course, you could manage that yourself with a
  214. little extra work, if it seems like a useful capability. If you
  215. don't change LDigits or RDigits, the default size of the BCD
  216. numbers will be 32 (20 to the left, 11 to the right, 1 for the
  217. sign).
  218.  
  219.                            BCD Math                      page 6
  220.  
  221.                            Unit: BCD
  222.  
  223.  
  224.  
  225. Before doing any BCD calculations, you must have some BCD
  226. numbers! The BCDSet routine takes a number in text string form
  227. and converts it to BCD:
  228.  
  229. TextSt := '1234567890.50';
  230. Nr := BCDSet(TextSt);
  231.    { FUNCTION BCDSet (TextSt: String): String; }
  232.  
  233. If your numbers are stored as actual numbers, you can convert
  234. them to a text string with Pascal's Str procedure, then to BCD:
  235.  
  236. Str(Number, TextSt);
  237. Nr := BCDSet(TextSt);
  238.  
  239. BCD numbers can also be converted back to text strings, of
  240. course. You may specify how many digits to the right of the
  241. decimal to keep (the number will be truncated, not rounded). If
  242. the RightDigits value is positive, trailing zeros will be kept;
  243. if negative, trailing zeros will be removed. There are also
  244. various formatting options which may be used. Here's how it
  245. works:
  246.  
  247. FUNCTION BCDFormat (Nr: String; HowToFormat,
  248.                     RightDigits: Integer): String;
  249.  
  250. The HowToFormat value may be any combination of the following
  251. (just add the numbers of the desired formats together):
  252.  
  253.    0   plain number
  254.    1   use commas to separate thousands, etc
  255.    2   start number with a dollar sign
  256.    4   put the sign on the right instead of the left side
  257.    8   use plus sign instead of space if nr is not negative
  258.  
  259. The BCD math functions are pretty much self-explanatory, so I'll
  260. keep the descriptions brief. The single-parameter functions are
  261. listed on the next page.
  262.  
  263.                            BCD Math                      page 7
  264.  
  265.                            Unit: BCD
  266.  
  267.  
  268.  
  269. { absolute value }
  270. FUNCTION BCDAbs (Nr: String): String;
  271.  
  272. { cosine }
  273. FUNCTION BCDCos (Nr: String): String;
  274.  
  275. { cotangent }
  276. FUNCTION BCDCot (Nr: String): String;
  277.  
  278. { cosecant }
  279. FUNCTION BCDCsc (Nr: String): String;
  280.  
  281. { convert degrees to radians }
  282. FUNCTION BCDDeg2Rad (Nr: String): String;
  283.  
  284. { the constant "e" }
  285. FUNCTION BCDe: String;
  286.  
  287. { factorial }
  288. FUNCTION BCDFact (Nr: Integer): String;
  289.  
  290. { fractional part of number }
  291. FUNCTION BCDFrac (Nr: String): String;
  292.  
  293. { integer part of number }
  294. FUNCTION BCDInt (Nr: String): String;
  295.  
  296. { negation }
  297. FUNCTION BCDNeg (Nr: String): String;
  298.  
  299. { the constant "pi" }
  300. FUNCTION BCDpi: String;
  301.  
  302. { convert radians to degrees }
  303. FUNCTION BCDRad2Deg (Nr: String): String;
  304.  
  305. { secant }
  306. FUNCTION BCDSec (Nr: String): String;
  307.  
  308. { signum }
  309. FUNCTION BCDSgn (Nr: String): Integer;
  310.  
  311. { sine }
  312. FUNCTION BCDSin (Nr: String): String;
  313.  
  314. { square root }
  315. FUNCTION BCDSqrt (Nr: String): String;
  316.  
  317. { tangent }
  318. FUNCTION BCDTan (Nr: String): String;
  319.  
  320.                            BCD Math                      page 8
  321.  
  322.                            Unit: BCD
  323.  
  324.  
  325.  
  326. Notes on the single-parameter functions:
  327.  
  328.   The signum function returns an integer based on the sign of
  329.   the BCD number:
  330.  
  331.      -1   if the BCD number is negative
  332.       0   if the BCD number is zero
  333.       1   if the BCD number is positive
  334.  
  335.   BCDpi is accurate to the maximum level afforded by the BCD
  336.   functions. BCDe is accurate to as many as 115 decimal places.
  337.   The actual accuracy, of course, depends on the size of BCD
  338.   numbers you've chosen.
  339.  
  340.   The trigonometric functions (cos, sin, tan, sec, csc, cot)
  341.   expect angles in radians. BCDDeg2Rad and BCDRad2Deg will allow
  342.   you to convert back and forth between radians and degrees.
  343.  
  344.  
  345.  
  346. Here is a list of the two-parameter functions:
  347.  
  348.  
  349. { addition }
  350. FUNCTION BCDAdd (Nr1, Nr2: String): String;
  351.  
  352. { divide 1st by 2nd }
  353. FUNCTION BCDDiv (Nr1, Nr2: String): String;
  354.  
  355. { multiplication }
  356. FUNCTION BCDMul (Nr1, Nr2: String): String;
  357.  
  358. { subtract 2nd from 1st }
  359. FUNCTION BCDSub (Nr1, Nr2: String): String;
  360.  
  361. { raise to a power }
  362. FUNCTION BCDPower (Nr: String; Power: Integer): String;
  363.  
  364. { compare two numbers }
  365. FUNCTION BCDCompare (Nr1, Nr2: String): Integer;
  366.  
  367. The comparison function returns an integer which reflects how
  368. the two numbers compare to each other:
  369.  
  370.    -1   Nr1 < Nr2
  371.     0   Nr1 = Nr2
  372.     1   Nr1 > Nr2
  373.  
  374.                         Equipment Info                   page 9
  375.  
  376.                         Unit: Equipment
  377.  
  378.  
  379.  
  380. The equipment unit gives you information about the computing
  381. environment. This includes both installed software and hardware.
  382.  
  383. The first function allows you to determine if an "enhanced"
  384. keyboard (101-key) is installed. It may not be able to figure
  385. out what the keyboard is on some older not-quite-clone PCs, in
  386. which case it will take the safe way out and report that there
  387. is no enhanced keyboard. This function returns -1 if there is an
  388. enhanced keyboard present, 0 if not.
  389.  
  390. FUNCTION EnhKbd: Integer;
  391.  
  392. Want to know the type of processor (CPU) being used? Can do!
  393.  
  394. FUNCTION Processor: Integer;
  395.  
  396. The results will be reported as a number which can be decoded as
  397. follows:
  398.  
  399.    0    NEC V20
  400.    1    8088 or 8086
  401.    2    80186
  402.    3    80286
  403.    4    80386
  404.    5    80486
  405.  
  406. Maybe you'd like to check for a CD-ROM drive:
  407.  
  408. FUNCTION CDROM: Integer;
  409.  
  410. This tells you how many logical drives exist, if there is a
  411. CD-ROM available. If not, it will return 0. Note that the CD-ROM
  412. installation check conflicts with the GRAPHICS.COM installation
  413. check for DOS 4.0, due to some screw-up at IBM or Microsoft. I'm
  414. not yet sure whether DOS 5.0 is similarly afflicted.
  415.  
  416. The number of floppy drives installed is retrieved with this:
  417.  
  418. FUNCTION Floppies: Integer;
  419.  
  420. To get the number of serial (COM) ports and parallel (LPT)
  421. ports, use the following functions:
  422.  
  423. FUNCTION CommPorts: Integer;
  424.  
  425. FUNCTION PrtPorts: Integer;
  426.  
  427.                         Equipment Info                  page 10
  428.  
  429.                         Unit: Equipment
  430.  
  431.  
  432.  
  433. Now, there may be up to four floppy drives in a system; however,
  434. the AT CMOS data area only directly supports two. This makes it
  435. easy to find out what kind of drives the first two are, but not
  436. the second two, if any. Such is life.
  437.  
  438. PROCEDURE FloppyType (VAR Drive1, Drive2: Integer);
  439.  
  440. The results from FloppyType are returned as follows:
  441.  
  442.    0    no drive
  443.    1    5 1/4"    360K
  444.    2    5 1/4"    1.2M
  445.    3    3 1/2"    720K
  446.    4    3 1/2"    1.44M
  447.    5    3 1/2"    2.88M
  448.  
  449. Result codes of 6-7 are also available, but are not yet defined.
  450.  
  451. New memory types sure have burgeoned over the years... expanded,
  452. extended, and now XMS. There are routines to check all of these:
  453.  
  454. { amount of extended memory installed }
  455. FUNCTION AllExtMem: LongInt;
  456.  
  457. { BIOS extended memory available }
  458. FUNCTION GetExtM: LongInt
  459.  
  460. { amount of expanded memory  (a page is 16 Kbytes) }
  461. PROCEDURE GetEMSm (VAR TotalPages, FreePages: Integer);
  462.  
  463. { amount of XMS memory  (returned in kilobytes) }
  464. PROCEDURE GetXMSm (VAR LargestFreeBlock, TotalFree: LongInt);
  465.  
  466. When you're dealing with extended memory, whether it be
  467. BIOS-type or using the XMS standard, the results are returned in
  468. kilobytes. Multiply 'em by 1024 to convert to bytes. When you're
  469. dealing with expanded memory (EMS), the results are in pages of
  470. 16,384 bytes.
  471.  
  472.                         Equipment Info                  page 11
  473.  
  474.                         Unit: Equipment
  475.  
  476.  
  477.  
  478. A few more routines to get the versions of the EMS and XMS
  479. drivers, if any:
  480.  
  481. PROCEDURE GetEMSv (VAR MajorV, MinorV: Integer);
  482.  
  483. PROCEDURE GetXMSv (VAR MajorV, MinorV: Integer);
  484.  
  485. These return the major and minor version numbers as two separate
  486. integers. For example, EMS 4.0 would return major version 4,
  487. minor version 0.
  488.  
  489. It's nice to know a little about the operating environment. With
  490. the below routines, you can find out what the DOS version is;
  491. what version of 4DOS, if any, is in use; and whether Microsoft
  492. Windows is running.
  493.  
  494. PROCEDURE GetDOSv (VAR MajorV, MinorV: Integer);
  495.  
  496. PROCEDURE Get4DOSv (VAR MajorV, MinorV: Integer);
  497.  
  498. PROCEDURE WinCheck (VAR MajorV, MinorV: Integer);
  499.  
  500. These return results as major and minor version numbers, as
  501. discussed above. The Get4DOSv and WinCheck routines return
  502. zeroes if 4DOS and Windows, respectively, are not in use.
  503.  
  504. There are a couple of curious features of GetDOSv to keep in
  505. mind. If the version is 10 or higher, you're running under OS/2.
  506. DOS version 10 is actually OS/2 1.0, version 20 is OS/2 2.0, and
  507. so on. Secondly, if you're using DOS 5.0, the version reported
  508. may not be 5.0-- DOS 5.0 can be told to reply with a lower
  509. version number to allow badly written older software to run
  510. properly.
  511.  
  512. One final routine that should be of some value is the one that
  513. allows you to find out what kind of display is available. It
  514. tells you the specific adapter and whether the display is color
  515. or monochrome. There is one case in which it can be confused,
  516. however-- if the adapter is CGA, the display is assumed to be
  517. color, since there is no way for the computer to know any
  518. differently. So, although this routine provides a good idea of
  519. what is available, it would be a good idea to provide an option
  520. to tell the program that a monochrome display is attached.
  521. Microsoft normally uses "/B" for this purpose, so that might be
  522. a good standard to stick with.
  523.  
  524. PROCEDURE GetDisplay (VAR Adapter: Integer; VAR Mono: Boolean);
  525.  
  526. The adapter will be one of the following:
  527.  
  528.    1     MDA                  4     EGA
  529.    2     Hercules             5     MCGA
  530.    3     CGA                  6     VGA
  531.  
  532.                      Expression Evaluator               page 12
  533.  
  534.                          Unit: ExtMath
  535.  
  536.  
  537.  
  538. The expression evaluator solves numeric equations. It allows you
  539. to find the result of an expression contained in a string.
  540. Normal algebraic precedence is used, e.g. 4+3*5 evaluates to 19.
  541. The usual numeric operators (*, /, +, -, ^) are supported
  542. (multiply, divide, add, subtract, and raise to a power).
  543. Negation is also supported. Parentheses can be used for
  544. overriding the default order of operations.
  545.  
  546. You may use either double asterisk ("**") or caret ("^") symbols
  547. to indicate exponentiation.
  548.  
  549. The constant PI is recognized, as are the following functions:
  550.    ABS    absolute value        INT    integer
  551.    ACOS   inverse cosine        LOG    natural log
  552.    ASIN   inverse sine          SIN    sine
  553.    ATAN   inverse tangent       SQRT   square root
  554.    COS    cosine                TAN    tangent
  555.    FRAC   fraction
  556.  
  557. Trig functions expect angles in radians.
  558.  
  559. To evaluate an expression, you pass it to the evaluator as a
  560. string. You will get back either an error code or a real result.
  561. See the CALC.PAS program for a working example.
  562.  
  563. PROCEDURE Evaluate (Expression: String; VAR Result: Real;
  564.                     VAR ErrCode: Integer);
  565.  
  566. An expression evaluator adds convenience to any program that
  567. needs to accept numbers. Why make someone reach for a calculator
  568. when number crunching is what a computer does best?
  569.  
  570.                  Extensions to Pascal's Math            page 13
  571.  
  572.                         Unit: ExtMath
  573.  
  574.  
  575.  
  576. For the most part, the math routines in this library are
  577. designed to provide alternatives to the math routines that come
  578. with Pascal. Still, Pascal's own math support is quite adequate
  579. for many purposes, so there's no sense in ignoring it. Here are
  580. some functions which improve on Pascal's math.
  581.  
  582. { inverse cosine }
  583. FUNCTION ArcCos (Number: Real): Real;
  584.    { 1.0 >= Number >= -1.0 }
  585.  
  586. { inverse hyperbolic cosine }
  587. FUNCTION ArcCosH (Number: Real): Real;
  588.  
  589. { inverse cotangent }
  590. FUNCTION ArcCot (Number: Real): Real;
  591.  
  592. { inverse hyperbolic cotangent }
  593. FUNCTION ArcCotH (Number: Real): Real;
  594.  
  595. { inverse cosecant }
  596. FUNCTION ArcCsc (Number: Real): Real;
  597.  
  598. { inverse hyperbolic cosecant }
  599. FUNCTION ArcCscH (Number: Real): Real;
  600.  
  601. { inverse secant }
  602. FUNCTION ArcSec (Number: Real): Real;
  603.  
  604. { inverse hyperbolic secant }
  605. FUNCTION ArcSecH (Number: Real): Real;
  606.  
  607. { inverse sine }
  608. FUNCTION ArcSin (Number: Real): Real;
  609.    { 1.0 >= Number >= -1.0 }
  610.  
  611. { inverse hyperbolic sine }
  612. FUNCTION ArcSinH (Number: Real): Real;
  613.  
  614. { inverse hyperbolic tangent }
  615. FUNCTION ArcTanH (Number: Real): Real;
  616.  
  617. { ceiling: smallest integer >= specified number }
  618. FUNCTION Ceil (Number: Real): Real;
  619.  
  620. { hyperbolic cosine }
  621. FUNCTION CosH (Number: Real): Real;
  622.  
  623. { cotangent }
  624. FUNCTION Cot (Number: Real): Real;
  625.  
  626.                  Extensions to Pascal's Math            page 14
  627.  
  628.                         Unit: ExtMath
  629.  
  630.  
  631.  
  632. { cosecant }
  633. FUNCTION Csc (Number: Real): Real;
  634.  
  635. { convert degrees to radians }
  636. FUNCTION Deg2Rad (Number: Real): Real;
  637.  
  638. { the constant "e" }
  639. FUNCTION e: Real;
  640.  
  641. { error function }
  642. FUNCTION Erf (Number: Real): Real;
  643.  
  644. { factorial }
  645. FUNCTION Fact (Number: Integer): Real;
  646.  
  647. { floor: largest integer <= specified number }
  648. FUNCTION Floor (Number: Real): Real;
  649.  
  650. { log (base 10) }
  651. FUNCTION Log (Number: Real): Real;
  652.  
  653. { convert radians to degrees }
  654. FUNCTION Rad2Deg (Number: Real): Real;
  655.  
  656. { raise a number to a power }
  657. FUNCTION Raise (Number: Real; Power: Integer): Real;
  658.  
  659. { secant }
  660. FUNCTION Sec (Number: Real): Real;
  661.  
  662. { hyperbolic secant }
  663. FUNCTION SecH (Number: Real): Real;
  664.  
  665. { signum (integer) }
  666. FUNCTION SgnI (Number: Integer): Integer);
  667.  
  668. { signum (real) }
  669. FUNCTION SgnR (Number: Real): Integer);
  670.  
  671. { hyperbolic sine }
  672. FUNCTION SinH (Number: Real): Real;
  673.  
  674. { tangent }
  675. FUNCTION Tan (Number: Real): Real;
  676.  
  677. { hyperbolic tangent }
  678. FUNCTION TanH (Number: Real): Real;
  679.  
  680.                        Joystick Support                 page 15
  681.  
  682.                         Unit: Joystick
  683.  
  684.  
  685.  
  686. There's little enough to say about the joystick. A PC may have
  687. up to two of them. Normally, a joystick has two buttons, and
  688. returns a pair of coordinates which describe the position in
  689. which it is being held. The coordinates vary depending on the
  690. individual joystick, the computer involved, and other factors,
  691. so it is wise to provide a calibration routine to customize your
  692. program for the joystick(s) involved.
  693.  
  694. The FlightStick joystick has a dial for throttle control, which
  695. is available only in a one-joystick setup. The throttle value is
  696. returned as the Y coordinate of an imaginary second joystick.
  697.  
  698. Coordinates (X, Y), where X is the horizontal and Y the vertical
  699. coordinate, range from around 0 to around 150 on my FlightStick.
  700. Since these values may vary significantly, however, they are
  701. returned as words.
  702.  
  703. The state of the joystick buttons may be checked individually or
  704. all at once. If you need to know the state of multiple buttons,
  705. it is faster to do it all at once, but you may do it either way.
  706.  
  707. FUNCTION ButtonA1: Boolean;       { button 1 on 1st joystick }
  708. FUNCTION ButtonA2: Boolean;       { button 2 on 1st joystick }
  709. FUNCTION ButtonB1: Boolean;       { button 1 on 2nd joystick }
  710. FUNCTION ButtonB2: Boolean;       { button 2 on 2nd joystick }
  711.  
  712. PROCEDURE Buttons (VAR A1, A2, B1, B2: Boolean); { all buttons }
  713.  
  714. The joystick positions are handled internally by a rather
  715. unfortunate method involving a timer, due to the way IBM
  716. designed the joystick interface. This makes getting the position
  717. rather slow. To alleviate the problem, all positions are
  718. returned at once.
  719.  
  720. PROCEDURE Positions (VAR AX, AY, BX, BY: Word);
  721.  
  722. Joystick support is handled through a set of BIOS routines which
  723. were added to the PC around 1985. These routines are not present
  724. in some of the oldest PCs.
  725.  
  726.                        Keyboard Control                 page 16
  727.  
  728.                         Unit: Keyboard
  729.  
  730.  
  731.  
  732. The keyboard is not a particularly exciting or glamorous device.
  733. In fact, we tend to forget about it except when it gets in the
  734. way. Sometimes it's a hardware problem-- squishy or clacking
  735. keys, or perhaps a commonly-used key placed in an out-of-the-way
  736. location. Then again, sometimes it's the software that's the
  737. problem. There are many aspects of keyboard control, not all of
  738. which are necessarily related to input. This unit will let you
  739. handle the keyboard in ways you may not have realized were
  740. possible. Better yet, it can help make keyboard control easier
  741. than the users of your programs dreamed possible.
  742.  
  743. Let's start out with keyboard output. Yep, not input-- output.
  744. We can stuff up to 15 keys into the keyboard buffer. Why would
  745. we ever want to do this? Perhaps to allow your program to pop-up
  746. a TSR automatically, to start another program after your program
  747. ends, or for creating key macros. You can enter extended key
  748. codes (like function keys) by using CHR$(0) before the scan
  749. code.
  750.  
  751. PROCEDURE TypeIn (Keys: String);
  752.  
  753. The usual keyboard action is quite sluggish. We can make it a
  754. lot crisper by changing the key repeat rate and the delay before
  755. repeating. This will work on ATs, but not PC/XT systems.
  756.  
  757. PROCEDURE SpeedKey (RepDelay, RepRate: Integer);
  758.  
  759. The delay may be 0-3 (1 by default):
  760.  
  761.    0      250 milliseconds
  762.    1      500 milliseconds
  763.    2      750 milliseconds
  764.    3        1 second
  765.  
  766. The repeat rate may be 0-31 (11 by default). The larger the
  767. number, the slower the speed-- 0 is around 30 cps, and 31 is
  768. around 2 cps.
  769.  
  770. I generally prefer to have the keyboard cranked up to full
  771. speed, using RepDelay and RepRate both set to zero. This may be
  772. a bit too zippy for some people, and may cause keyboard buffer
  773. overflows with some games. Experiment with it to see what you
  774. like best.
  775.  
  776. Of course, there may be reasons to make keyboard repeat less
  777. sensitive instead! That might be a good idea in programs written
  778. for small children, for example. You can adjust the keyboard
  779. equally well in either direction.
  780.  
  781.                        Keyboard Control                 page 17
  782.  
  783.                         Unit: Keyboard
  784.  
  785.  
  786.  
  787. Pascal allows you to control one of the keys which can interrupt
  788. your program, namely the Break key. There's another dangerous
  789. key which PasWiz allows you to control-- the PrtSc (PrintScreen)
  790. key. PrtSc may not seem like a hazard at first glance, but if
  791. it's pressed by accident with no printer ready, or in a graphics
  792. mode which PrtSc doesn't understand how to print, the results
  793. can be pretty messy. So, we let you turn it off or on:
  794.  
  795. PROCEDURE SetPrtSc (PrtScON: Boolean);
  796.  
  797. Use FALSE to turn it off or TRUE to turn it back on. If you turn
  798. off PrtSc, you MUST remember to turn it back on again before
  799. your program ends! Otherwise, an interrupt vector will point
  800. into nowhere, causing probable chaos the next time PrtSc is
  801. pressed.
  802.  
  803. Regardless of whether you've turned the PrtSc key off, you can
  804. print the screen yourself just as if PrtSc had been pressed:
  805.  
  806. PROCEDURE PrintScreen;
  807.  
  808. Now here's a strange one for you. When IBM brought out the
  809. 101-key keyboard, called the "enhanced" keyboard, they did
  810. something bizarre to the BIOS. They still allowed old keyboard
  811. calls to work, but they filtered out the new key codes so no one
  812. would see them. This made sure that no one would be able to use
  813. the capabilities of the "enhanced" keyboard without rewriting
  814. their programs. So, the keyboard has been around for years, and
  815. there are still few programs that even notice when you press
  816. F11. Pascal does not support the enhanced keyboard at all.
  817. Fortunately, PasWiz -does-. You can find out if an enhanced
  818. keyboard is installed with the EnhKbd function, which is in the
  819. Equipment unit.
  820.  
  821. If there is an enhanced keyboard installed, you can activate it
  822. with this:
  823.  
  824. PROCEDURE SetEnhKbd (Enhanced: Boolean);
  825.  
  826. With enhanced keyboard support activated, all key requests that
  827. used the old services are translated to the new services. So,
  828. SetEnhKbd affects the ReadKey (in the CRT unit that comes with
  829. Pascal) and other Pascal functions as well as other PasWiz
  830. keyboard routines. Note that you MUST deactivate enhanced
  831. keyboard support before ending your program. Otherwise, an
  832. interrupt vector will point into nowhere, probably causing a
  833. crash on the next keypress!
  834.  
  835.                        Keyboard Control                 page 18
  836.  
  837.                         Unit: Keyboard
  838.  
  839.  
  840.  
  841. If you're about to request important input, you may not want to
  842. chance having it answered from results of the keyboard buffer--
  843. could be that the user meant those keys for another purpose. In
  844. that case, it's a good approach to clear out the keyboard buffer
  845. just before the input:
  846.  
  847. PROCEDURE ClearKbd;
  848.  
  849. No keyboard unit would be complete without a selection of
  850. routines to check the shift states and get or set the keyboard
  851. toggles. Let's start with the toggles, which are so called
  852. because they get toggled from one state to another:
  853.  
  854. FUNCTION CapsOn: Boolean;         { Caps Lock }
  855.  
  856. FUNCTION InsertOn: Boolean;       { Insert }
  857.  
  858. FUNCTION NumOn: Boolean;          { Num Lock }
  859.  
  860. FUNCTION ScrollOn: Boolean;       { Scroll Lock }
  861.  
  862. You can also turn the toggles off or on. It's courteous to
  863. restore the original toggle states once you end your program, so
  864. you might want to save the original values for that purpose.
  865. Then again, I guess that doesn't apply if your program is
  866. designed for the specific purpose of setting the toggles!
  867.  
  868. PROCEDURE SetCaps (CapsLock: Boolean);        { Caps Lock }
  869.  
  870. PROCEDURE SetInsert (InsertKey: Boolean);     { Insert }
  871.  
  872. PROCEDURE SetNum (NumLock: Boolean);          { Num Lock }
  873.  
  874. PROCEDURE SetScroll (ScrollLock: Boolean);    { Scroll Lock }
  875.  
  876. Does anyone actually use ScrollLock for anything?  Just
  877. curious...
  878.  
  879.                        Keyboard Control                 page 19
  880.  
  881.                         Unit: Keyboard
  882.  
  883.  
  884.  
  885. The shift keys are unique in many respects. They don't return
  886. codes that can be detected with ReadKey or stuffed into the
  887. keyboard buffer; several can be pressed at the same time; and
  888. they don't repeat. You can detect 'em with PasWiz, at any rate:
  889.  
  890. FUNCTION AltPress: Boolean;         { any ALT }
  891.  
  892. FUNCTION CtrlPress: Boolean;        { any CTRL }
  893.  
  894. FUNCTION ShiftPress: Boolean;       { any SHIFT }
  895.  
  896. FUNCTION LAltPress: Boolean;        { left ALT }
  897.  
  898. FUNCTION LCtrlPress: Boolean;       { left CTRL }
  899.  
  900. FUNCTION LShiftPress: Boolean;      { left SHIFT }
  901.  
  902. FUNCTION RAltPress: Boolean;        { right ALT }
  903.  
  904. FUNCTION RCtrlPress: Boolean;       { right CTRL }
  905.  
  906. FUNCTION RShiftPress: Boolean;      { right SHIFT }
  907.  
  908. NOTE that LAltPress, LCtrlPress, RAltPress, and RCtrlPress are
  909. ONLY available for enhanced keyboards. They will not return
  910. useful results on older keyboards.
  911.  
  912.                          String Stuff                   page 20
  913.  
  914.                          Unit: Strings
  915.  
  916.  
  917.  
  918. Strings have always been something of an afterthought in Pascal.
  919. This unit brings in the heavy artillery! The PasWiz string
  920. routines may be divided into the following categories:
  921. comparison, compression, encryption, extraction, searching, and
  922. miscellaneous (mostly alteration). Let's take up these
  923. categories one at a time.
  924.  
  925. The compression routines are designed to work with ordinary text
  926. strings. The strings may not contain IBM extended-ASCII codes
  927. (CHR($80)-CHR($FF)), as these are used in the compression.
  928. Compression works on spaces, which will give you an average of
  929. 15% compression on normal text. If you compress printable text
  930. (i.e., no control codes), you'll get printable text in return,
  931. which makes these routines handy for use with text files.
  932. Compression and decompression is done at an extreme rate of
  933. speed and will not affect the timing of your program in any
  934. noticeable fashion.
  935.  
  936. FUNCTION Bsq (St: String): String;     { compress a string }
  937.  
  938. FUNCTION BUsq (St: String): String;    { uncompress a string }
  939.  
  940. Comparing two strings is easy enough in Pascal, but not as
  941. flexible as might be desired for some applications. You can tell
  942. if two strings match exactly, but not if they're reasonably
  943. close matches. PasWiz has two fuzzy comparison routines which
  944. can help.
  945.  
  946. The Soundex routine uses a long-established algorithm to
  947. convert a word into a code which represents the sound of the
  948. word. It is fast and can work well under properly defined
  949. circumstances; for instance, it will tell you that "Smith"
  950. sounds just like "Smythe", but not like "Banks". Between the
  951. need for speed and the vagaries of the English language,
  952. however, you may find matches which don't work as well. Soundex
  953. is certain that "Knight" sounds just like "Smashed", for
  954. example. So, it may be perfect for something like a phone book,
  955. but not for a spelling checker!
  956.  
  957. FUNCTION Soundex (St: String): String;
  958.  
  959. The Bickel routine, on the other hand, tells you how closely two
  960. words match. This is a relative measure, not an absolute
  961. measure, so you'd probably want to search through an entire
  962. dictionary and just keep the words which matched best. The
  963. Bickel algorithm is slower than Soundex but is much more
  964. precise.
  965.  
  966. FUNCTION Bickel (St1, St2: String): Integer;
  967.  
  968.                          String Stuff                   page 21
  969.  
  970.                          Unit: Strings
  971.  
  972.  
  973.  
  974. There are many cases in which you might want to keep data
  975. private. The PasWiz encryption routines provide a simple and
  976. extremely fast method for password-protecting text. The
  977. encryption technique is trivial and will not withstand any
  978. concerted attack, but should suffice for casual use. It will
  979. help if you pick a longish password of unusual characters, for
  980. example '[^.mE@@&o}' (don't use this example itself, please)!
  981.  
  982. There are two encryption routines (which also work as decryption
  983. routines). The first is designed to produce printable, if
  984. bizarre-looking, results which are suited for use with text
  985. files. Text to be encrypted by this routine may not include IBM
  986. extended-ASCII characters (CHR($80) - CHR($FF)), since these are
  987. used to insure printable text.
  988.  
  989. FUNCTION CipherP (St, Passwd: String): String;
  990.  
  991. The other routine will work with any sort of text, but is not
  992. guaranteed to produce printable results. So, it's not suited for
  993. use with text files.
  994.  
  995. FUNCTION Cipher (St, Passwd: String): String;
  996.  
  997. Of the extraction routines, two are merely convenient
  998. rephrasings of the Copy function which allow you to grab a
  999. substring from the left or right side of a string:
  1000.  
  1001. FUNCTION Left (St: String; Len: Integer): String;
  1002.  
  1003. FUNCTION Right (St: String; Len: Integer): String;
  1004.  
  1005. Another extraction routine is more interesting. It allows you to
  1006. extract a substring from a string which contains delimited
  1007. information. For instance, consider the following name and
  1008. address string. It has three fields, each separated by an
  1009. asterisk. We can use Extract to grab any individual field:
  1010.  
  1011. St := 'Tom Hanlin*3544 E. Southern Ave. #104*Mesa, AZ 85204';
  1012. FOR PrtAddress := 1 TO 3 DO BEGIN
  1013.    AddressLine := Extract(St, '*', PrtAddress);
  1014.    WriteLn(AddressLine);
  1015. END;
  1016.  
  1017. The extract function is defined as follows:
  1018.  
  1019. FUNCTION Extract (St, Delimiter: String;
  1020.                   Index: Integer): String;
  1021.  
  1022. If you try to extract a field which doesn't exist, a null string
  1023. will be returned. Field delimiters may be anything at all, by
  1024. the way-- one possible use for Extract might be to block-read a
  1025. text file, splitting it apart in memory by using the carriage
  1026. return and linefeed as a delimiter.
  1027.  
  1028.                        String Stuff                     page 22
  1029.  
  1030.                        Unit: Strings
  1031.  
  1032.  
  1033.  
  1034. PasWiz provides an assortment of string search routines. One is
  1035. a simple modification of Pos which allows you to start the
  1036. search at a given place in the string:
  1037.  
  1038. FUNCTION Instr (Start: Integer; SubSt, St: String): Integer;
  1039.  
  1040. Another works like Pos, but returns the last match rather than
  1041. the first match:
  1042.  
  1043. FUNCTION RPos (SubSt, St: String): Integer;
  1044.  
  1045. Of course, you don't always want to search for something in
  1046. specific. You might be more interested in finding the first
  1047. character that fits into a given category or categories, like
  1048. perhaps numbers or letters. No problem:
  1049.  
  1050. FUNCTION TypePos (ChType: Integer; St: String): Integer;
  1051.  
  1052. The ChType value is formed by adding the numbers which represent
  1053. the desired categories. This can also be used to search for the
  1054. first character which is not of a given type, since the
  1055. categories are exclusive:
  1056.  
  1057.     1    alphabetic
  1058.     2    numeric
  1059.     4    symbols
  1060.     8    control codes (ASCII 0-31, 127)
  1061.    16    graphics codes (ASCII 128-255)
  1062.    32    space (ASCII 32)
  1063.  
  1064. That covers the string routines which can be readily
  1065. categorized. Most of the remaining routines are designed to
  1066. alter a string in one way or another. This includes being able
  1067. to remove selected characters, substrings, types of characters,
  1068. or repeated characters from a string; trimming the left or right
  1069. side of a string of blanks; converting to uppercase, lowercase,
  1070. or using the correct capitalization for a proper name; replacing
  1071. one substring with another; reversing a string; and forming a
  1072. new string by repeating a given substring.
  1073.  
  1074. The "case", "trim", and "reverse" functions are pretty much
  1075. self-explanatory:
  1076.  
  1077. FUNCTION LowerCase (St: String): String;    { lowercase }
  1078.  
  1079. FUNCTION NameCase (St: String): String;     { name case }
  1080.  
  1081. FUNCTION UpperCase (St: String): String;    { upper case }
  1082.  
  1083. FUNCTION LTrim (St: String): String;        { left trim }
  1084.  
  1085. FUNCTION RTrim (St: String): String;        { right trim }
  1086.  
  1087. FUNCTION Reverse (St: String): String;      { reverse }
  1088.  
  1089.                        String Stuff                     page 23
  1090.  
  1091.                        Unit: Strings
  1092.  
  1093.  
  1094.  
  1095. The Crunch function removes adjacent repetitions of a substring.
  1096. This is particularly handy for parsing user input, for example--
  1097. you can use it to remove repeated spaces between options, etc.
  1098.  
  1099. FUNCTION Crunch (SubSt, St: String): String;
  1100.  
  1101. The Dupe function forms a string by repeating a substring. It's
  1102. handy when you need a string of a given number of spaces,
  1103. zeroes, or nulls. It can also be used for drawing horizontal
  1104. lines and other applications.
  1105.  
  1106. FUNCTION Dupe (Count: Integer; SubSt: String): String;
  1107.  
  1108. There are many times when it's nice to be able to replace all
  1109. occurrences of one substring with another. PasWiz can do that,
  1110. no problem. You don't have to worry about recursion, either--
  1111. each occurrence is replaced only once, even if the replacement
  1112. substring contains the target substring.
  1113.  
  1114. FUNCTION Replace (OldSubSt, NewSubSt, St: String): String;
  1115.  
  1116. Of course, you can delete a substring by replacing it with a
  1117. null string. It's faster to use the routine designed for that
  1118. purpose, though:
  1119.  
  1120. FUNCTION StripSt (SubSt, St: String): String;
  1121.  
  1122. You may also delete specified characters from a string:
  1123.  
  1124. FUNCTION StripCh (ChList, St: String): String;
  1125.  
  1126. Next, a routine which deletes specified types of characters from
  1127. a string. This can be very good for screening user input.
  1128.  
  1129. FUNCTION StripType (ChType: Integer; St: String): String;
  1130.  
  1131. The ChType value is formed by adding the numbers which represent
  1132. the desired categories:
  1133.  
  1134.     1    alphabetic
  1135.     2    numeric
  1136.     4    symbols
  1137.     8    control codes (ASCII 0-31, 127)
  1138.    16    graphics codes (ASCII 128-255)
  1139.    32    space (ASCII 32)
  1140.  
  1141. PasWiz also has a specialized variant on the Val function which
  1142. converts a number from a string to a WORD (or INTEGER) value. No
  1143. error checking is provided. This is very small and fast:
  1144.  
  1145.    FUNCTION WVal (St: STRING): WORD;
  1146.  
  1147.                             Music                       page 24
  1148.  
  1149.                          Unit: Music
  1150.  
  1151.  
  1152.  
  1153. Granted, the PC has never been known for its wonderful sound
  1154. capabilities. Still, it has more potential than you might guess,
  1155. especially given the utterly minimal Sound/Delay/NoSound
  1156. routines that are provided with Pascal. The Music unit makes it
  1157. much easier to use sounds by providing an actual music language.
  1158. The BACHINV and ENTERTNR demo programs demonstrate some of the
  1159. possibilities.
  1160.  
  1161. The PasWiz music language is nearly identical to that offered by
  1162. the BASIC PLAY statement. The major difference is that the "MB"
  1163. command (play the music as a background task) is not supported.
  1164. I'll add that later, if I get enough requests.
  1165.  
  1166. There are only two music procedures:
  1167.  
  1168. PROCEDURE ResetMF;
  1169.  
  1170. PROCEDURE PlayMF(Sounds: String);
  1171.  
  1172. The ResetMF procedure is used to reset all music parameters to
  1173. the default values. It would typically be used after finishing a
  1174. song to restore the music handler for the next song.
  1175.  
  1176. The PlayMF procedure is the one that does the real work. Here's
  1177. a list of the music commands supported:
  1178.  
  1179.    MB  play music as a background task (ignored)
  1180.    MF  play music as a foreground task (ignored)
  1181.    ML  legato (8/8 note length)
  1182.    MN  normal music (7/8 note length)
  1183.    MN  staccato (6/8 note length)
  1184.    Ln  Length of notes (n = 1-64; note length = 1/n)
  1185.    Nn  Note number (n = 0-84; 0 is a rest)
  1186.    On  Octave (n = 0-6, default 4)
  1187.    Pn  Pause (n = 1-64; pause length = 1/n)
  1188.    Tn  Tempo (n = 32-255, default 120; quarter notes/minute)
  1189.    <   move up an octave (max 6)
  1190.    >   move down an octave (min 0)
  1191.  
  1192. You can also use the actual letters of the notes (C, D, E, F, G,
  1193. A, and B). If you're not particularly musical, these correspond
  1194. to "do, re, mi, fa, so, la, ti" (with the final "do" being C
  1195. again, but an octave higher). To play a scale, you'd use
  1196. 'CDEFGAB>C'. The notes may be followed by dots, by note lengths,
  1197. and by sharp or flat symbols (a '+' or '#' for a sharp, a '-'
  1198. for a flat). For example, 'D-.' is a dotted D flat. The dot
  1199. means that the note will play for half again its usual length.
  1200. Dots can be repeated.
  1201.  
  1202. I might note (ahem) that the so-called "ANSI" music offered by
  1203. some BBSes and comm programs is based on this same music
  1204. language. If you're writing telecomm software, this unit makes
  1205. it trivial to add sound.
  1206.  
  1207.                             Mouse                       page 25
  1208.  
  1209.                          Unit: Mouse
  1210.  
  1211.  
  1212.  
  1213. Considering the ubiquity of the mouse these days, it's a marvel
  1214. to me that none of the popular programming languages provides
  1215. any support for it. Well, BASIC supports it via light pen
  1216. emulation, but that scarcely counts. Anyway, this is a simple
  1217. little unit which provides you direct access to the mouse
  1218. driver. It will work with any Microsoft-compatible mouse driver.
  1219.  
  1220. A few words are necessary on mouse handling. To begin with, the
  1221. best time to check for a mouse is immediately after you've
  1222. established the desired video mode. The mouse driver initializes
  1223. certain information when you check for it, so it's a good idea
  1224. to check for it only once, at the appropriate time.
  1225.  
  1226. The mouse cursor was implemented in a rather bizarre manner. If
  1227. you call ShowCursor, you're guaranteed that the mouse cursor
  1228. will be visible; however, this also increments an internal
  1229. visibility flag. If you call ShowCursor multiple times, you will
  1230. also have to call HideCursor multiple times before the dang
  1231. cursor actually disappears.
  1232.  
  1233. The mouse driver was apparently implemented without any thought
  1234. for the future. In text mode, it returns coordinates based on
  1235. CGA hi-res graphics mode-- 640x200 instead of the expected
  1236. 80x25. If you use the mouse driver in text mode, you'll have to
  1237. compensate for this (divide coordinates by 8 to convert to text
  1238. mode, or multiply by 8 to convert to the mouse virtual mode).
  1239. The CGA low-res 320x200 graphics mode is implemented likewise.
  1240. It seems Microsoft thought that 640x200 would be the ultimate
  1241. resolution, so they translated everything to a 640x200 virtual
  1242. mode. Arrgh. Fortunately, this does not apply to video modes
  1243. other than text and CGA graphics.
  1244.  
  1245. I understand that it's possible to get the mouse working in
  1246. Hercules graphics mode, but I'm not sure what the details are.
  1247. If anyone out there knows, please let me know, and I'll pass it
  1248. along.
  1249.  
  1250. Since Microsoft was initially very tight-lipped about the mouse
  1251. functions, older mouse drivers for Microsoft-compatible rodents
  1252. don't necessarily have all the functions available (this
  1253. includes Logitech, amazingly enough). The Microsoft mouse driver
  1254. continues to be updated in a rapid and haphazard manner, so
  1255. keeping up-to-date is no guarantee. However, if you have any
  1256. problems with these routines, you can almost certainly clear
  1257. them up by getting a newer mouse driver. The routines in this
  1258. unit are almost all old, well-established functions. "Iffy" ones
  1259. are marked for your convenience.
  1260.  
  1261.                             Mouse                       page 26
  1262.  
  1263.                          Unit: Mouse
  1264.  
  1265.  
  1266.  
  1267. The first function to consider simply tells you whether a mouse
  1268. is available, and if so, how many buttons it has. It also resets
  1269. the mouse driver, so it should be used only at the beginning of
  1270. your program (or after changing the video mode).
  1271.  
  1272. FUNCTION Init: Integer;
  1273.    { returns 0 if no mouse, else # of buttons }
  1274.  
  1275. Most often, you'll want to know which mouse button(s) are
  1276. pressed and where the mouse cursor is:
  1277.  
  1278. FUNCTION LeftButton: Boolean;
  1279.    { TRUE if pressed }
  1280.  
  1281. FUNCTION MidButton: Boolean;
  1282.    { always FALSE on 2-button rodents }
  1283.  
  1284. FUNCTION RightButton: Boolean;
  1285.    { TRUE if pressed }
  1286.  
  1287. FUNCTION WhereX: Integer;
  1288.    { X-coord (see notes on previous page) }
  1289.  
  1290. FUNCTION WhereY: Integer;
  1291.    { Y-coord (see notes on previous page) }
  1292.  
  1293. As well as finding the current mouse information, it's possible
  1294. to find out what the mouse has been doing since you last
  1295. checked. Two sets of routines exist: one to find out how many
  1296. times a button was pressed and where it was at the last press,
  1297. and one to find out how many times a button was released and
  1298. where it was at the last release.
  1299.  
  1300. PROCEDURE LeftClick(VAR Count, X, Y: Integer);
  1301.  
  1302. PROCEDURE MidClick(VAR Count, X, Y: Integer);
  1303.  
  1304. PROCEDURE RightClick(VAR Count, X, Y: Integer);
  1305.  
  1306. PROCEDURE LeftRelease(VAR Count, X, Y: Integer);
  1307.  
  1308. PROCEDURE MidRelease(VAR Count, X, Y: Integer);
  1309.  
  1310. PROCEDURE RightRelease(VAR Count, X, Y: Integer);
  1311.  
  1312.                             Mouse                       page 27
  1313.  
  1314.                          Unit: Mouse
  1315.  
  1316.  
  1317.  
  1318. There's one more informational routine. It tells you the basic
  1319. mouse software and hardware stats: driver version, connector
  1320. type (serial, bus, etc), and IRQ used. This routine is slightly
  1321. hazardous in that, although Microsoft claims it has existed from
  1322. the first, other manufacturers (including Logitech) have taken
  1323. some time to implement it. In other words, it may not return
  1324. useful information. The routine conducts a self-check and will
  1325. return all zeroes if it suspects the information is not good,
  1326. but even so... proceed with care.
  1327.  
  1328. PROCEDURE Info(VAR Version: Real; VAR Connector, IRQ: Byte);
  1329.  
  1330. Connector info: 1=bus, 2=serial, 3=InPort, 4=PS/2,
  1331. 5=Hewlett-Packard IRQs: 0=PS/2; 2-5, 7 are actual IRQ numbers.
  1332. It is conceivable that higher IRQ numbers may be supported on
  1333. AT-type machines, though not by Microsoft.
  1334.  
  1335. Of course, you can set mouse info as well as retrieving it. The
  1336. following routines are pretty well self-explanatory (don't
  1337. forget the notes about the strange text-mode and CGA coordinate
  1338. handling, and cursor handling):
  1339.  
  1340. { hide the mouse cursor }
  1341. PROCEDURE HideCursor;
  1342.  
  1343. { (maybe) make the cursor visible }
  1344. PROCEDURE ShowCursor;
  1345.  
  1346. { set the cursor position }
  1347. PROCEDURE GotoXY(X, Y: Integer);
  1348.  
  1349. { set the cursor range }
  1350. PROCEDURE Window(X1, Y1, X2, Y2: Integer);
  1351.  
  1352. There are other possibilities supported by the mouse driver that
  1353. I have not implemented here. They're mostly on the rather
  1354. esoteric side and are not supported by anything except recent
  1355. Microsoft mouse drivers and perhaps some close compatibles, such
  1356. as Logitech.
  1357.  
  1358. Among the mouse capabilities I haven't implemented are finding
  1359. out how fast and in what direction the mouse is moving, the
  1360. coordinate size of the screen as far as the mouse is concerned,
  1361. finding out the video modes that the mouse driver understands,
  1362. setting mouse speed and sensitivity parameters, setting up an
  1363. interrupt-driven system for handling mouse events, and a few
  1364. others.
  1365.  
  1366.                             Mouse                       page 28
  1367.  
  1368.                          Unit: Mouse
  1369.  
  1370.  
  1371.  
  1372. None of these missing capabilities is particularly vital (or
  1373. even useful) for the average mouse application. However, if
  1374. you're interested in any of these capabilities, let me know
  1375. which ones, and I'll be glad to add them to PasWiz.
  1376.  
  1377. Note: if you're confused at how I can get away with duplicating
  1378. the names of existing procedures... well, it's easy enough.
  1379. Let's consider WhereX. It means one thing to Pascal's Crt unit
  1380. and another to the PasWiz Mouse unit. Since the Mouse unit
  1381. doesn't use the Crt unit, it has no problem with any ambiguity.
  1382. Existing programs that don't use the Mouse unit will likewise
  1383. have no problems, since they don't know about the new routine.
  1384. Suppose you want to use both the Crt and Mouse units together,
  1385. however? There's the rub!
  1386.  
  1387. You can specify a routine from a given unit by including the
  1388. unit name when you use the routine. For instance:
  1389.  
  1390. X := Mouse.WhereX;      { get the mouse cursor position }
  1391.  
  1392. X := Crt.WhereX;        { get the normal cursor position }
  1393.  
  1394. This allows multiple units to use the same names for things.
  1395. While this may seem like a bit of a pain, since you have to
  1396. specify which you want, it has a major built-in advantage if
  1397. used properly. What's properly? When a routine in one unit works
  1398. just like a routine by the same name in another unit. When I
  1399. call the mouse routine "WhereX", for instance, I've also told
  1400. you what it is for and how to use it. So, the name itself
  1401. contains a lot of useful information on how to use the routine!
  1402. That's what I call a major advantage.
  1403.  
  1404.